﻿Shader "Unlit/OutLighting"
{
    Properties
    {
        [HDR]_AtmoColor("光晕颜色", Color) = (1, 0, 0, 1)
        _OutLightSize("光晕范围", Float) = 0.1
        _OutLightPow("光晕扩散度", Float) = 1
        _OutLightStrength("光晕强度", Float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent"}
        LOD 100

        ZWrite Off
        Cull Front
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM

            #pragma vertex Vertex
            #pragma fragment Fragment

            // GPU Instancing
            #pragma multi_compile_instancing

            #include "UnityCG.cginc"

            half4 _AtmoColor;
            half _OutLightSize;
            half _OutLightPow;
            half _OutLightStrength;

            struct VertexInput
            {
                half4 position : POSITION;
                half3 normal : NORMAL;
                float2 uv : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct VertexOutput
            {
                half4 position : SV_POSITION;
                half3 positionWS : TEXCOORD0;
                half3 normalWS : TEXCOORD1;

                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            VertexOutput Vertex(VertexInput input)
            {
                VertexOutput output = (VertexOutput)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

                half3 positionWS = mul(unity_ObjectToWorld, float4(input.position.xyz, 1.0));
                half4 positionCS = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));

                // 将法线变换到NDC空间
                half3 viewNormal = mul((half3x3)UNITY_MATRIX_IT_MV, input.normal.xyz);
                half3 ndcNormal = normalize(mul((half3x3)UNITY_MATRIX_P, viewNormal));

                // 将近裁剪面右上角位置的顶点变换到观察空间
                half4 nearUpperRight = mul(unity_CameraInvProjection, half4(1, 1, UNITY_NEAR_CLIP_VALUE, _ProjectionParams.y));

                // 求得屏幕宽高比
                half aspect = abs(nearUpperRight.y / nearUpperRight.x);
                ndcNormal.x *= aspect;

                half4 posSV = positionCS;
                posSV.xy += _OutLightSize * ndcNormal.xy;

                output.position = posSV;
                output.positionWS = positionWS;
                output.normalWS = UnityObjectToWorldNormal(input.normal);

                return output;
            }

            half4 Fragment(VertexOutput input) : SV_TARGET
            {
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

                input.normalWS = normalize(input.normalWS);

                // 视角法线
                half3 viewdir = normalize(input.positionWS.xyz - _WorldSpaceCameraPos.xyz);

                half4 color = _AtmoColor;

                // 视角法线与模型法线点积形成中间指为1向四周逐渐衰减为0的点积值，赋给透明通道，形成光晕效果
                half number = saturate(dot(viewdir, normalize(input.normalWS)));

                color.a = pow(number, _OutLightPow);
                color.a = saturate(color.a * _OutLightStrength * number);
                return color;
            }

            ENDCG
        }
    }
}
